<template>
  <div class="slide-captcha">
    <div class="range" :class="rangeStatus ? 'success' : ''">
      <div class="background" ref="leftBox"></div>
      <el-icon @mousedown="rangeMove" @touchstart.stop="handleTouchStart">
        <SuccessFilled v-if="rangeStatus" />
        <DArrowRight v-else />
      </el-icon>
      <span :class="rangeStatus ? 'success' : ''">{{
        rangeStatus ? '验证成功' : '请按住滑块拖动到最右边'
      }}</span>
    </div>
    <div style="width: 3px; height: 1px"></div>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { DArrowRight, SuccessFilled } from '@element-plus/icons-vue'

const emit = defineEmits(['success', 'failure'])
const disX = ref(0)
const rangeStatus = ref(false)
const leftBox = ref()

// 滑块移动
const rangeMove = (e) => {
  const ele = e.target
  const startX = e.clientX
  const eleWidth = ele.offsetWidth
  const parentWidth = ele.parentElement.offsetWidth - 6
  const MaxX = parentWidth - eleWidth
  if (rangeStatus.value) {
    // 不运行
    return false
  }
  document.onmousemove = (e) => {
    const endX = e.clientX
    disX.value = endX - startX
    if (disX.value <= 0) {
      disX.value = 0
    }
    if (disX.value >= MaxX - eleWidth) {
      // 减去滑块的宽度,体验效果更好
      disX.value = MaxX
    }
    ele.style.transition = '.1s all'
    ele.style.transform = 'translateX(' + disX.value + 'px)'
    e.preventDefault()
  }
  document.onmouseup = () => {
    leftBox.value.style.width = 0 + 'px'
    leftBox.value.style.transition = '.5s all'
    if (disX.value !== MaxX) {
      ele.style.transition = '.5s all'
      ele.style.transform = 'translateX(0)'
      // 失败
      emit('failure')
    } else {
      rangeStatus.value = true
      // 成功
      emit('success')
    }
    document.onmousemove = null
    document.onmouseup = null
  }
}
const handleTouchStart = (e) => {
  console.log('touch start', e)
  const ele = e.target
  const touch = e.touches[0]
  const startX = touch.clientX
  const eleWidth = ele.offsetWidth
  const parentWidth = ele.parentElement.offsetWidth - 6
  const MaxX = parentWidth - eleWidth
  if (rangeStatus.value) {
    // 不运行
    return false
  }
  document.ontouchmove = (e) => {
    const touch = e.touches[0]
    const endX = touch.clientX
    disX.value = endX - startX
    if (disX.value <= 0) {
      disX.value = 0
    }
    if (disX.value >= MaxX - eleWidth) {
      // 减去滑块的宽度,体验效果更好
      disX.value = MaxX
    }
    ele.style.transition = '.1s all'
    ele.style.transform = 'translateX(' + disX.value + 'px)'
  }
  document.ontouchend = () => {
    leftBox.value.style.width = 0 + 'px'
    leftBox.value.style.transition = '.5s all'
    if (disX.value !== MaxX) {
      ele.style.transition = '.5s all'
      ele.style.transform = 'translateX(0)'
      // 失败
      emit('failure')
    } else {
      rangeStatus.value = true
      // 成功
      emit('success')
    }
    document.onmousemove = null
    document.onmouseup = null
  }
}
</script>

<style lang="scss" scoped>
@mixin flex-center {
  display: flex;
  justify-content: center;
  align-items: center;
}

.slide-captcha {
  width: 100%;
  .range {
    background-color: #d5deed;
    position: relative;
    transition: 1s all;
    user-select: none;
    color: #585858;
    @include flex-center;
    height: 46px;
    border-radius: 4px;
    box-sizing: border-box;
    &.success {
      background-color: #7bc23cbe;
      color: #fff;
      i {
        color: #4092ff;
      }
    }
    .el-icon {
      position: absolute;
      left: 3px;
      width: 46px; /*no*/
      height: 40px;
      color: #b5b5b5;
      background-color: #fff;
      cursor: pointer;
      font-size: 16px;
      @include flex-center;
      user-select: none;
      border-radius: 1px;
    }

    .background {
      width: 0;
      height: 100%;
      background-color: #4092ff;
      position: absolute;
      left: 0;
    }

    span {
      font-size: 14px;
      font-family: 'PingFang SC';
      color: #b4b4b4;

      &.success {
        color: white;
      }
    }
  }
}
:deep(.el-icon) {
  svg {
    user-select: none;
    pointer-events: none;
  }
}
</style>
